﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;

namespace Common.Tools
{
    public class XmlHelper
    {
        string _xmlName = "moolly";
        string _xmlNameSpace = "http://www.imooly.com";

        XmlDocument xmlDoc = new XmlDocument();

        /// <summary>
        /// 递归创建节点
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="element"></param>
        /// <param name="dic"></param>
        /// <returns></returns>
        private List<XmlNode> XmlAddChilds(XmlDocument doc, XmlElement element, Dictionary<string, object> dic)
        {
            List<XmlNode> retData = new List<XmlNode>();
            foreach (string key in dic.Keys)
            {
                XmlElement inElement = doc.CreateElement(key);
                if (dic[key] is Dictionary<string, object>)
                {
                    List<XmlNode> nodes = XmlAddChilds(doc, inElement, dic[key] as Dictionary<string, object>);
                    foreach (XmlNode node in nodes)
                    {
                        inElement.AppendChild(node);
                    }
                }
                else if (dic[key] is string)
                {
                    string inText = HttpUtility.HtmlDecode(dic[key] as string);
                    inElement.InnerText = inText;
                }
                retData.Add(inElement);
            }
            return retData;
        }

        /// <summary>
        /// 创建xml文件，有则重建
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="rootNode"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public bool CreateXmlFile(Dictionary<string, object> dic, string rootNode, string fileName)
        {
            if (System.IO.File.Exists(fileName))
            {
                System.IO.File.Delete(fileName);
            }
            XmlDocument doc = new XmlDocument();
            XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, _xmlName, _xmlNameSpace);
            doc.AppendChild(declaration);
            XmlElement root = doc.CreateElement(rootNode);
            List<XmlNode> nodes = XmlAddChilds(doc, root, dic);
            foreach (XmlNode node in nodes)
            {
                root.AppendChild(node);
            }
            doc.AppendChild((XmlNode)root);
            doc.Save(fileName);
            return true;
        }

        public bool CreateEmptyXml(string fileName, string rootNode)
        {
            if (System.IO.File.Exists(fileName))
            {
                System.IO.File.Delete(fileName);
            }
            XmlDocument doc = new XmlDocument();
            XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, _xmlName, _xmlNameSpace);
            doc.AppendChild(declaration);
            XmlElement root = doc.CreateElement(rootNode);
            doc.AppendChild((XmlNode)root);
            doc.Save(fileName);
            return true;
        }

        /// <summary>
        /// 添加更节点下元素，有则修改。文件不存在就创建
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="root"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool AddTopItem(string fileName, string root, string key, string value)
        {
            if (System.IO.File.Exists(fileName) == false)
            {
                CreateEmptyXml(fileName, root);
            }
            XmlDocument doc = new XmlDocument();
            doc.Load(fileName);
            XmlNode parent = doc.SelectSingleNode(root);
            if (parent == null) return false;
            XmlNode node = parent.SelectSingleNode(key);
            string inText = HttpUtility.HtmlDecode(value);
            if (node == null)       //不存在
            {
                XmlElement element = doc.CreateElement(key);
                element.InnerText = inText;
                parent.AppendChild(element);
            }
            else
            {
                node.InnerText = inText;
            }
            doc.Save(fileName);
            return true;
        }

        /// <summary>
        /// 获取跟节点下的key值
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="root"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string ReadTopItem(string fileName, string root, string key)
        {
            if (System.IO.File.Exists(fileName) == false)
            {
                return null;
            }
            XmlDocument doc = new XmlDocument();
            doc.Load(fileName);
            XmlNode parent = doc.SelectSingleNode(root);
            if (parent == null) return null;
            XmlNode node = parent.SelectSingleNode(key);
            return HttpUtility.HtmlEncode(node.InnerText);
        }

        private bool HaveChildItem(XmlDocument doc, XmlNode node)
        {
            if (node.ChildNodes == null || node.ChildNodes.Count == 0) return false;
            Dictionary<string, object> retDic = new Dictionary<string, object>();
            if (retDic.Count > 1) return true;
            foreach (XmlNode _node in node.ChildNodes)
            {
                if (_node.ChildNodes == null || _node.ChildNodes.Count == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            return false;
        }

        private Dictionary<string, object> ReadAddChilds(XmlDocument doc, XmlNode node)
        {
            if (node.ChildNodes == null || node.ChildNodes.Count == 0) return null;
            Dictionary<string, object> retDic = new Dictionary<string, object>();
            foreach (XmlNode _node in node.ChildNodes)
            {
                if (HaveChildItem(doc, _node) == false)
                {
                    retDic.Add(_node.Name, _node.InnerText/*HttpUtility.HtmlEncode(_node.InnerText)*/);
                }
                else
                {
                    retDic.Add(_node.Name, ReadAddChilds(doc, _node));
                }
            }
            return retDic;
        }

        /// <summary>
        /// 读取整个结构（跟节点以下），object为string 或者Dictionary
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, object> ReadXmlFile(string fileName, string root)
        {
            if (System.IO.File.Exists(fileName) == false)
            {
                return null;
            }
            XmlDocument doc = new XmlDocument();
            doc.Load(fileName);
            XmlNode parent = doc.SelectSingleNode(root);
            if (parent == null) return null;
            Dictionary<string, object> retDic = new Dictionary<string, object>();
            foreach (XmlNode node in parent.ChildNodes)
            {
                if (HaveChildItem(doc, node) == false)  //没有子项
                {
                    retDic.Add(node.Name, node.InnerText/*HttpUtility.HtmlEncode(node.InnerText)*/);
                }
                else
                {
                    Dictionary<string, object> dic = ReadAddChilds(doc, node);
                    retDic.Add(node.Name, dic);
                }
            }
            return retDic;
        }

        /*
            XmlReadWriter rw = new XmlReadWriter();
            
            Dictionary<string, object> second = new Dictionary<string, object>();
            second.Add("SecondKey1", "SecondValue1");
            second.Add("SecondKey2", "SecondValue2");
            second.Add("SecondKey3", "SecondValue3");
            second.Add("SecondKey4", "SecondValue4");
            Dictionary<string, object> top = new Dictionary<string, object>();
            top.Add("FirstKey1", "FirstValue1");
            top.Add("FirstKey2", second);
            top.Add("FirstKey3", "FirstValue3");

            //构建xml树
            rw.CreateXmlFile(top, "Goods", "sample.xml");

            //添加一个item
            rw.AddTopItem("sample.xml", "Goods", "AddKey", "AddValuexxxx");

            string strValue = rw.ReadTopItem("sample.xml", "Goods", "AddKey");
            
            //读整个文档
            Dictionary<string, object> dic = rw.ReadXmlFile("sample.xml", "Goods");

         */

    }
}
